www.gusucode.com > Simulink Model API Generation 程序工具箱matlab源码 > Simulink Model API Generation/SimulinkAPIAutomation/generateSimulinkAPI.m
function generateSimulinkAPI(systemName,varargin) % Helps to generate the Model Construction Simulink API codes for given % Model or Subsystem. % %Syntax: % >> generateSimulinkAPI(systemName) % Prints the API for the given system in the command window. % % >> generateSimulinkAPI(systemName,filename) % Writes the API for the given system in the specified file. % % systemName - It can be a simulink model or the subsystem. % % Example: % >> generateSimulinkAPI('sldemo_absbrake') % Prints the API for the 'sldemo_absbrake' in the command window. % % >> generateSimulinkAPI('sldemo_absbrake','sample.m') % Writes the API for the 'sldemo_absbrake' in the file 'sample.m'. % % Contact: contactus@sysenso.com % %-------------------------------------------------------------------------- %% Validate inputs. if nargin>1 fid = fopen(varargin{1},'W+'); else fid = 1; end %-------------------------------------------------------------------------- load_system(systemName); if strcmpi(systemName,bdroot(systemName)) modelLevelAPI = true; else modelLevelAPI = false; end %-------------------------------------------------------------------------- %% Add commands to create a new model. fprintf(fid,'%s\n',['modelName = ''' systemName '_API'';']); fprintf(fid,'%s\n','new_system(modelName);'); %-------------------------------------------------------------------------- %% Get all the blocks of a given System and run iteratively add API commands. modelBlocks = find_system(systemName,'LookUnderMasks','on'); fprintf(fid,'%s\n','% Add Blocks and set the block position. '); for ii = 2:numel(modelBlocks) % Get the positions of the blocks. % Check library reference. if ~(isempty(get_param(modelBlocks{ii},'ReferenceBlock'))) srcPath = get_param(modelBlocks{ii},'ReferenceBlock'); destPath = strrep(modelBlocks{ii},systemName,''); destPath = strrep(destPath,char(10),[''' char(10) ''']); fprintf(fid,'%s\n',['add_block([''' srcPath '''],[modelName,''' destPath ''']);']); elseif strcmp(get_param(modelBlocks{ii},'BlockType'),'ModelReference') % Check Model reference. srcPath = getSimulinkPath('ModelReference'); srcPath = strrep(srcPath,char(10),[''' char(10) ''']); destPath = strrep(modelBlocks{ii},systemName,''); destPath = strrep(destPath,char(10),[''' char(10) ''']); mdlRef = get_param(modelBlocks{ii},'ModelName'); fprintf(fid,'%s\n',['add_block([''' srcPath '''],[modelName,''' destPath ''']);']); fprintf(fid,'%s\n',['set_param([modelName,''' destPath '''],''ModelName'',''' mdlRef ''');']); else % Get sourcePath of the blocks using getSimulinkPath() function. srcPath = getSimulinkPath(get_param(modelBlocks{ii},'BlockType')); srcPath = strrep(srcPath,char(10),[''' char(10) ''']); destPath = strrep(modelBlocks{ii},systemName,''); destPath = strrep(destPath,char(10),[''' char(10) ''']); blkType = get_param(modelBlocks{ii},'BlockType'); dialParams = get_param(modelBlocks{ii},'DialogParameters'); if ~ isempty(dialParams) dialProps = fieldnames(dialParams); end blkParams = get_param(modelBlocks{ii},'objectParameters'); blkProps = fieldnames(blkParams); if strcmp(blkType,'SubSystem') % To make the getSimulinkPath to locate the correct subsystem % path. blkType = 'Subsystem'; end if ~strcmp(blkType,'Subsystem') % API commands for the blocks. fprintf(fid,'%s\n',['add_block([''' srcPath '''],[modelName,''' destPath ''']);']); else % For Masked sub systems. if strcmp(get_param(modelBlocks{ii},'mask'),'on') srcPath = getSimulinkPath(blkType); srcPath = strrep(srcPath,char(10),[''' char(10) ''']); fprintf(fid,'%s\n',['add_block([''' srcPath '''],[modelName,''' destPath ''']);']); fprintf(fid,'%s\n',['delete_line([modelName,''' destPath '''],''In1/1'',''Out1/1'');']); fprintf(fid,'%s\n',['delete_block([modelName,''' destPath '/In1'']);']); fprintf(fid,'%s\n',['delete_block([modelName,''' destPath '/Out1'']);']); if isfield(get_param(modelBlocks{ii},'ObjectParameters'),'MaskObject') % Latest version. generateMaskAPI(modelBlocks{ii},destPath,fid); else % Older version. fprintf(fid,'%s\n',['set_param([modelName,''' destPath '''],''Mask'',''on'')']); end else % For subSystems. srcPath = getSimulinkPath(blkType); srcPath = strrep(srcPath,char(10),[''' char(10) ''']); fprintf(fid,'%s\n',['add_block([''' srcPath '''],[modelName,''' destPath ''']);']); fprintf(fid,'%s\n',['delete_line([modelName,''' destPath '''],''In1/1'',''Out1/1'');']); fprintf(fid,'%s\n',['delete_block([modelName,''' destPath '/In1'']);']); fprintf(fid,'%s\n',['delete_block([modelName,''' destPath '/Out1'']);']); end end %------------------------------------------------------------------ % Set dialog parametes. for jj = 1:numel(dialProps) try propValue = get_param(modelBlocks{ii},dialProps{jj}); refValue = get_param(getSimulinkPath(blkType),dialProps{jj}); catch exceptionObj if (strcmp(exceptionObj.identifier,'Simulink:Commands:ParamUnknown')) refValue = ''; continue; else rethrow(exceptionObj); end end res = isequal(propValue,refValue); if (~(res) && ~strcmp(dialProps{jj},'IsSubsystemVirtual')) if isnumeric(get_param(modelBlocks{ii},dialProps{jj})) fprintf(fid,'%s\n',['set_param([modelName,''' destPath '''],''' dialProps{jj} ''',[' num2str(get_param(modelBlocks{ii},dialProps{jj})) ']);']); elseif ~ isstruct(dialProps{jj}) ischar(get_param(modelBlocks{ii},dialProps{jj})); outString = get_param(modelBlocks{ii},dialProps{jj}); outString = strrep(outString, '''' , ''''''); outString = strrep(outString,'char(10)',[''' char(10) ''']); fprintf(fid,'%s\n',['set_param([modelName,''' destPath '''],''' dialProps{jj} ''',''' outString ''');']); end end end end %------------------------------------------------------------------ % Block Properties. for jj = 1:numel(blkProps) % Check the read-only attribute if ~(strcmp(blkParams.(blkProps{jj}).Attributes{1},'read-only')) try propValue = get_param(modelBlocks{ii},blkProps{jj}); refValue = get_param(getSimulinkPath(blkType),blkProps{jj}); catch exceptionObj if (strcmp(exceptionObj.identifier,'Simulink:Commands:ParamUnknown')) else rethrow(exceptionObj); end end res = isequal(propValue,refValue); if (~(res) && ~strcmp(blkProps{jj},'CurrentBlock')) if isnumeric(get_param(modelBlocks{ii},blkProps{jj})) fprintf(fid,'%s\n',['set_param([modelName,''' destPath '''],''' blkProps{jj} ''',[' num2str(get_param(modelBlocks{ii},blkProps{jj})) ']);']); elseif isstr(get_param(modelBlocks{ii},blkProps{jj})) %if(strcmp(blkProps{jj},'MaskDisplay')) outString = get_param(modelBlocks{ii},blkProps{jj}); outString = strrep(outString, '''' , ''''''); fprintf(fid,'%s\n',['set_param([modelName,''' destPath '''],''' blkProps{jj} ''',[''' strrep(outString,char(10),[''' char(10) ''']) ''']);' ]); else % TODO : handle the cell array and structure. end end end end end %---------------------------------------------------------------------- %% Set Signal Properties. portHandles = get_param(modelBlocks{ii},'PortHandles'); outProps = get_param(portHandles.Outport,'ObjectParameters'); if ~(isempty(outProps)) blkType = get_param(modelBlocks{ii},'BlockType'); refPortHandles = get_param(getSimulinkPath(blkType),'PortHandles'); refOutProps = get_param(refPortHandles.Outport,'ObjectParameters'); outFields = fieldnames(outProps); destPath = strrep(modelBlocks{ii},systemName,''); destPath = strrep(destPath,char(10),[''' char(10) ''']); fprintf(fid,'%s\n',['portHandles' num2str(ii-1) ' = get_param([modelName, ''' destPath '''],''PortHandles'');']); for jj = 1:numel(outFields) if ~(strcmp(outProps.(outFields{jj}).Attributes{1},'read-only')) if ~(strcmp(outFields{jj},'SignalObject') || strcmp(outFields{jj},'PropagatedSignals')) srcValue = get_param(portHandles.Outport,outFields{jj}); refValue = get_param(refPortHandles.Outport,outFields{jj}); if ~strcmp(srcValue,refValue) if isnumeric(get_param(portHandles.Outport,outFields{jj})) fprintf(fid,'%s\n',['set_param(portHandles' num2str(ii-1) '.Outport,''' outFields{jj} ''',''' mat2str(get_param(portHandles.Outport,outFields{jj})) ''');']); else fprintf(fid,'%s\n',['set_param(portHandles' num2str(ii-1) '.Outport,''' outFields{jj} ''',''' get_param(portHandles.Outport,outFields{jj}) ''');']); end end end end end end %-------------------------------------------------------------------------- %% Draw Lines. fprintf(fid,'%s\n','% Adding Lines.'); lineH = find_system(systemName,'findAll','on','LookUnderMasks','on','type','line'); for ii = 1:numel(lineH) srcBlkHandle = get_param(lineH(ii),'SrcBlockHandle'); linePath = get_param(srcBlkHandle,'Parent'); linePath = strrep(linePath,systemName,''); linePath = strrep(linePath,char(10),[''' char(10) ''']); linePts = get_param(lineH(ii),'Points'); fprintf(fid,'%s\n',['add_line([modelName,''' linePath '''],' mat2str(linePts) ');']); end %-------------------------------------------------------------------------- %% Annotations fprintf(fid,'%s\n','% Adding Annotations.'); antn = find_system(systemName,'FindAll','on','type','annotation'); dummyAntn = Simulink.Annotation([systemName '/dummy']); dummyAntnProps = get(dummyAntn); dummyAntnFields = fieldnames(dummyAntnProps); for ii = 1:numel(antn) antnProps = get(antn(ii)); antnPath = antnProps.Path; antnPath = strrep(antnPath,systemName,''); antnFields = fieldnames(antnProps); fprintf(fid,'%s\n',['antn' num2str(ii) ' = Simulink.Annotation([modelName ''' antnPath '/' strrep(antnProps.Text,char(10),[''' char(10) ''']) ''']);']); for jj = 1:numel(antnFields) if ~(strcmp(get(antn(ii),antnFields{jj}),get(dummyAntn,dummyAntnFields{jj}))) if isnumeric(get(antn(ii),antnFields{jj})) && ~strcmp(antnFields{jj},'Handle') fprintf(fid,'%s\n',['set(antn' num2str(ii) '(1),''' antnFields{jj} ''',[' num2str(get(antn(ii),antnFields{jj})) ']);']); elseif isstring(get(antn(ii),antnFields{jj})) fprintf(fid,'%s\n',['set(antn((1)' num2str(ii) '),''' antnFields{jj} ''',''' strrep(get(antn(ii),antnFields{jj}),char(10),[''' char(10) ''']) ''');']); end end end end delete(dummyAntn); %-------------------------------------------------------------------------- %% If the API is required for a subsystem level, then there is no need of model parameters and properties. if ~modelLevelAPI fprintf(fid,'%s\n','open_system(modelName);'); return; end %-------------------------------------------------------------------------- %% Model Properties. refModelPath = tempname; [path,refModelFile,ext] = fileparts(refModelPath); refModel = new_system(refModelFile); mdlProps = get_param(systemName,'objectParameters'); refMdlProps = get_param(refModel,'objectParameters'); mdlFields = fieldnames(mdlProps); refMdlFields = fieldnames(refMdlProps); for ii = 2: numel(mdlFields) %fprintf(fid,'%s\n',ii); if (~(strcmp(mdlProps.(mdlFields{ii}).Attributes{1},'read-only'))) && (~(strcmp(mdlProps.(mdlFields{ii}).Attributes{1},'write-only'))) && (~(strcmp(mdlProps.(mdlFields{ii}).Attributes{1},'dont-eval'))) && ~(strcmp(mdlFields{ii},'ProdEndianess')) && ~(strcmp(mdlFields{ii},'RTWOptions')) if ~(strcmp(get_param(systemName,mdlFields{ii}),get_param(refModel,refMdlFields{ii}))) if (isstr(get_param(systemName,mdlFields{ii}))) fprintf(fid,'%s\n',['set_param(modelName,''' mdlFields{ii} ''',[''' strrep(strrep(get_param(systemName, mdlFields{ii}),'''',''''''),char(10),[''' char(10) ''']) ''']);' ]); elseif (iscell(get_param(systemName,mdlFields{ii}))) value = get_param(systemName, mdlFields{ii}); fprintf(fid,'%s\n',['set_param(modelName,''' mdlFields{ii} ''',''' value{1} ''');' ]); end end end end bdclose(refModelFile); %-------------------------------------------------------------------------- %% Model Configuration Parameters. % Get the default configuration data. tempConfig = Simulink.ConfigSet; % Use a temporary file to store the model configuration parameters. tempConfigPath = tempname; [path,tempConfigFile,ext] = fileparts(tempConfigPath); tempConfigFile = [tempConfigFile '.m']; Simulink.BlockDiagram.saveActiveConfigSet(systemName, tempConfigFile); % Read line by line and parse the string to get the parameter and value. % Print the parameter only if the value is differing with the default % value. fileId = fopen(tempConfigFile); fileLine = fgetl(fileId); startMatch = true; while ischar(fileLine) previousLine = fileLine; fileLine = fgetl(fileId); if ~ischar(fileLine) break; end setParamMatch = regexp(fileLine,'^cs\.set_param\('); switchTargetMatch = regexp(fileLine,'^cs\.switchTarget\('); if ~isempty(switchTargetMatch) % TODO: continue; end if ~isempty(setParamMatch) if startMatch fprintf(fid,'%s\n',strrep(previousLine,char(10),[''' char(10) '''])); end startMatch = false; paramData = regexp(fileLine,'cs\.set_param\(\''(?<parameter>[\w]+)\''\,\s+\''(?<value>[\.\,\*\\\%\(\)\s\-\w]*)\''\)\;\s+(?<comment>.*)','names'); if ~isempty(paramData) try paramValue = tempConfig.get_param(paramData.parameter); catch exceptionObj if (exceptionObj.identifier == 'Simulink:ConfigSet:IgnoredParam') else rethrow(exceptionObj); end end % Process only if the values are not same. if ~isequal(paramData.value,paramValue) fprintf(fid,'%s\n',strrep(regexprep(fileLine,'cs\.set_param\(','set_param( modelName,'),char(10),[''' char(10) '''])); end else % Not able to handle with the regexp. Hence use it as it is. fprintf(fid,'%s\n',strrep(regexprep(fileLine,'cs\.set_param\(','set_param(modelName,'),char(10),[''' char(10) '''])); end elseif ~startMatch % Lines that didn't have cs.set_param. fprintf(fid,'%s\n',strrep(fileLine,char(10),[''' char(10) '''])); end end % Close and delete the file. fclose(fileId); delete(tempConfigFile); %-------------------------------------------------------------------------- fprintf(fid,'%s\n','open_system(modelName);'); if nargin>1 fclose(fid); end end